package com.lsz.crm; /**
 * @Author liushizhong
 * @Date 2021/10/9 19:23
 * @Version 1.0
 */

import com.alibaba.fastjson.JSON;
import com.lsz.crm.base.ResultInfo;
import com.lsz.crm.exceptions.AuthException;
import com.lsz.crm.exceptions.NoLoginException;
import com.lsz.crm.exceptions.ParamsException;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 全局异常处理
 */

@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver {

    /**
     *
     * @param request 请求对象
     * @param response 响应对象
     * @param handler 方法对象
     * @param ex 异常对象
     * @return
     */
    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response,
                                         Object handler, Exception ex) {

        /**
         * 非法请求拦截： 判断是否抛出未登录异常，如果抛出，则返回登录页
         */

        if(ex instanceof NoLoginException){
            // 重定向到登录页
            ModelAndView mv = new ModelAndView("redirect:/index");
            return mv;
        }


        /**
         * 设置默认异常处理（返回视图）
         */
        ModelAndView modelAndView = new ModelAndView("error");
        // 设置异常信息
        modelAndView.addObject("code",500);
        modelAndView.addObject("msg","系统异常，请重试...");

        // 判断方法返回值
        if(handler instanceof HandlerMethod){
            // 类型转换
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            // 获取方法上声明的注解
            ResponseBody responseBody = handlerMethod.getMethod().getDeclaredAnnotation(ResponseBody.class);
            // 判断对象是否为空,为空则表明返回视图，不为空则表明返回数据
            if(responseBody == null){
                /**
                 * 返回视图
                 */
                // 判断异常类型是否是自定义异常
                if(ex instanceof ParamsException){ // 参数异常
                    ParamsException paramsException = (ParamsException) ex;
                    // 设置异常信息
                    modelAndView.addObject("code",paramsException.getCode());
                    modelAndView.addObject("msg",paramsException.getMsg());
                }else if(ex instanceof AuthException){ // 认证异常
                    AuthException authException = (AuthException) ex;
                    // 设置异常信息
                    modelAndView.addObject("code",authException.getCode());
                    modelAndView.addObject("msg",authException.getMsg());
                }
                return modelAndView;

            }else {
                /**
                 * 返回数据（Json）
                 */

                // 设置默认的异常处理
                ResultInfo resultInfo = new ResultInfo();
                resultInfo.setCode(500);
                resultInfo.setMsg("系统异常，请重试!");

                // 判断异常是否是自定义异常
                if(ex instanceof ParamsException){ // 参数异常
                    ParamsException p = (ParamsException) ex;
                    // 设置异常信息
                    resultInfo.setMsg(p.getMsg());
                    resultInfo.setCode(p.getCode());
                }else if(ex instanceof AuthException){ // 认证异常
                    AuthException authException = (AuthException) ex;
                    // 设置异常信息
                    resultInfo.setMsg(authException.getMsg());
                    resultInfo.setCode(authException.getCode());
                }

                // 设置相应格式及编码格式【json】
                response.setContentType("application/json;charset=UTF-8");

                // 得到字符输出流
                PrintWriter out = null;
                try {
                    // 得到输出流
                    out = response.getWriter();
                    // 输出数据，将对象转为json格式的字符串
                    String json = JSON.toJSONString(resultInfo);
                    // 输出数据
                    out.write(json);
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    if(out != null){
                        out.close();
                    }
                }

                return null;
            }

        }

        return modelAndView;
    }
}
